from asm_parser import parser, code_content
from asm_lexer import lexer, tokens
from asm_coder import SymTable, AsmCoder
import sys
from functional import seq


class Coder():
    symTable = SymTable()
    coder = AsmCoder()
    address = 0
    symbol_index = 16

    def code_first(self, code: code_content):
        if code.type == code_content.L_INSTRUCTION:
            self.symTable.addEntry(code.l_label, self.address)
            self.address -= 1
        self.address += 1

    def code_second(self, code: code_content) -> str:
        if code.type == code_content.A_INSTRUCTION:
            if code.a_is_number:
                return self.coder.a_instr(code.a_number)
            else:
                a_label = code.a_label
                if not self.symTable.contains(a_label):
                    self.symTable.addEntry(a_label, self.symbol_index)
                    self.symbol_index += 1
                return self.coder.a_instr(self.symTable.getAddress(a_label))
        elif code.type == code_content.L_INSTRUCTION:
            pass
        elif code.type == code_content.C_INSTRUCTION:
            a = '1' if 'M' in code.c_comp else '0'
            return ''.join(['111', a,
                            self.coder.comp(code.c_comp),
                            self.coder.dest(code.c_dest),
                            self.coder.jump(code.c_jump)])
        return ""


def translate(filename, hackname):
    print("translate {}".format(filename))
    coder = Coder()
    with open(filename, 'r') as rfile:
        for line in rfile.readlines():
            result = parser.parse(line, lexer=lexer)
            if not result:
                continue
            coder.code_first(result)

    with open(filename, 'r') as rfile, open(hackname, 'w') as wfile:
        for line in rfile.readlines():
            result: code_content = parser.parse(line, lexer=lexer)
            if not result:
                continue
            hack = coder.code_second(result)
            if hack != "":
                wfile.write(hack + "\n")


def main():
    files = sys.argv[1:]
    #  files = ['./test.asm']
    seq(files).map(lambda file: translate(
        file, file.rstrip('\.asm') + '.hack2')).to_list()


if __name__ == '__main__':
    main()
